#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#include "proto.h"
#include "logic.h"
#include "spinlock.h"
#include <functional>
#include <math.h>
#include "httpclient.h"

LogicTask::LogicTask(boost::asio::io_service& io_context_ ,int id, string ip, short port, RobotRule rule)
	:AsyncTimer(&io_context_)
	,phone_num(id)
	,uid(getuid(phone_num))
	,session(connect(io_context_,ip,port),ip,port)
	, _rule(rule)
	, _on_seat(false)
{
	init();
	io_context = &io_context_;
	money = 0;
	last_mo_mj = 0;
	players.clear();
}

tcp::socket LogicTask::connect(boost::asio::io_service& io_context_, string ip, short port)
{
	tcp::socket s(io_context_);

		try {
			static SpinLock lock;
			SmartLock<SpinLock> smart(lock);
			tcp::resolver resolver(io_context_);
#ifdef WIN32
			boost::asio::connect(s, resolver.resolve(ip, to_string(port)));
#else
			tcp::resolver::query query(ip, to_string(port));
			boost::asio::connect(s, resolver.resolve(query));
#endif

			rbuf_.Reset();
			wbuf_.Reset();
		}
		catch (std::exception& e)
		{
			std::cout << s.native_handle() <<"connect error:" << e.what() << std::endl;
		}
	return move(s);
}

void LogicTask::run(void)
{
}

int LogicTask::random(int start, int end, double pow_num)
{
	srand(time(NULL));
	//if (pow_num == 1.0)
	{
		return start + (rand()) % (end - start + 1);
	}
// 	else
// 	{
// 		int between = end - start + 1;
// 		float per = ((rand() % 999) + 1) / 1000;//(0.001~0.999)
// 		int rand_num = between * pow(per, pow_num);
// 		return start + rand_num;
// 	}
}
string LogicTask::url = "";
int LogicTask::getuid(int id)
{
	stringstream sstr;
	sstr << "/Login?param={\"user\":\"" << id << "\",\"password\":\"123456\"}";
	auto rsp = http(*io_context, url, sstr.str());
	auto js = decode_json(rsp);
	if (js.isMember("data"))
	{
		auto data = js["data"];
		if (data.isMember("uid") && data["uid"].isInt())
		{
			int uid = data["uid"].asInt();
			return uid;
		}
	}
	string str("has no exist user");
	str.append(to_string(id));
	cout << str;
	exit(1);
	return 0;
}

int LogicTask::ping()
{
	Json::Value root;
	root["cmd"] = HEART_BEAT;
	string content = encode_json(root);
	do_write(content);
	return 0;
}

int LogicTask::join_room_req()
{
	Json::Value root;
	root["cmd"] = CLIENT_JOIN_ROOM_REQ;
	root["uid"] = uid;
	root["skey"] = "abc";
	string content = encode_json(root);
	do_write(content);
    return 0;
}

int LogicTask::ready_req()
{
	Json::Value root;
	root["cmd"] = CLIENT_READY_REQ;
	string content = encode_json(root);
	do_write(content);
  return 0;
}

int LogicTask::peng_req()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_PENG_REQ;
		root["uid"] = uid;
		string content = encode_json(root);
		do_write(content);
	};
	RunOnce(PengExpire(), func);
	return 0;
}

int LogicTask::ang_gang_req(int mj)
{
	will_angang_mj = mj;
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_ANG_GANG_REQ;
		root["uid"] = uid;
		root["angang_mj"] = will_angang_mj;
		string content = encode_json(root);
		do_write(content);
	};

	RunOnce(GangExpire(), func);

	return 0;
}

int LogicTask::ming_gang_req()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_MING_GANG_REQ;
		root["uid"] = uid;
		root["ming_gang_mj"] = last_mo_mj;
		string content = encode_json(root);
		do_write(content);
	};

	RunOnce(GangExpire(), func);

	return 0;
}

int LogicTask::fang_gang_req()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_FANG_GANG_REQ;
		root["uid"] = uid;
		string content = encode_json(root);
		do_write(content);
	};
	RunOnce(GangExpire(), func);
	return 0;
}

int LogicTask::out_mj_req()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_OUT_MJ_REQ;
		root["uid"] = uid;
		root["out_mj"] = choose_outmj().val;
		string content = encode_json(root);
		do_write(content);
// 		cout << "uid: " << uid << " input: " << last_mo_mj << " output: " << root["out_mj"].asInt() << endl;
	};
	
		RunOnce(Expire(), func);
	

	return 0;
}

int LogicTask::auto_out_mj_req()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_ROBOT_AUTO_OUT_MJ_REQ;
		root["uid"] = uid;
		string content = encode_json(root);
		do_write(content);
	};
	
		RunOnce(Expire(), func);
	
	return 0;
}

int LogicTask::zimo_hu_req()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_ZIMO_HU_REQ;
		root["uid"] = uid;
		string content = encode_json(root);
		do_write(content);
	};
		RunOnce(HuExpire(), func);
	
	return 0;
}

int LogicTask::fang_pao_hu()
{
	auto func = [this](const boost::system::error_code& err) {
		Json::Value root;
		root["cmd"] = CLIENT_FANG_PAO_HU_REQ;
		root["uid"] = uid;
		string content = encode_json(root);
		do_write(content);
	};
	RunOnce(GangExpire(), func);
	
	return 0;
}

int LogicTask::qiang_gang_hu()
{
  return 0;
}

int LogicTask::goldroom_logout_req()
{
	Json::Value root;
	root["cmd"] = CLIENT_GOLDROOM_LOGOUT_ROOM;
	root["uid"] = uid;
	string content = encode_json(root);
	do_write(content);
	return 0;
}

int LogicTask::do_ding_que(int dq)
{
	Json::Value root;
	root["cmd"] = CLIENT_DING_QUE_REQ;
	root["uid"] = uid;
	root["dq_val"] = dq;
	string content = encode_json(root);
	do_write(content);
	return 0;
}

int LogicTask::cancel_robot()
{
	Json::Value root;
	root["cmd"] = CLIENT_CANCEL_ROBOT_OP_REQ;
	string content = encode_json(root);
	do_write(content);
	return 0;
}

int LogicTask::recv_data(string content)
{
	//ptree root;
	read_root.clear();
	read_root = decode_json(content);
	int cmd = read_root["cmd"].asInt();
	//cout << "socket:" << socket_.native_handle() << " cmd: " << cmd << endl;
	if ( cmd == SERVER_ENTER_ROOM_UC )
	{
		  handler_cmd_SERVER_ENTER_ROOM_UC();
	}
	else if (cmd == SERVER_ROOM_INFO_BC)
	{
		  handler_cmd_SERVER_ROOM_INFO_BC();
	}
	else if (cmd == SERVER_GAME_START_BC)
	{
		  handler_cmd_SERVER_GAME_START_BC();
	}
  else if (cmd == SERVER_READY_BC)
	{
		  handler_cmd_SERVER_READY_BC();
	}
	else if (cmd == SERVER_GET_ONE_MJ)
	{
		  handler_cmd_SERVER_GET_ONE_MJ();
	}
	else if (cmd == SERVER_OUT_ONE_MJ)
	{
		  handler_cmd_SERVER_OUT_ONE_MJ();
	}
  else if (cmd == SERVER_OPERATE_CHECK_AFTER_GETIN_MJ)
  {
      handler_cmd_SERVER_OPERATE_CHECK_AFTER_GETIN_MJ();
  }
  else if (cmd == SERVER_OPERATE_CHECK_OTHERS_PUTOUT_MJ)
  {
      handler_cmd_SERVER_OPERATE_CHECK_OTHERS_PUTOUT_MJ();
  }
  else if (cmd == SERVER_OPERATE_CHECK_AFTER_PENG)
  {
      handler_cmd_SERVER_OPERATE_CHECK_AFTER_PENG();
  }    
  else if (cmd == SERVER_OPERATE_CHECK_QIANG_GANG_HU)
  {
      handler_cmd_SERVER_OPERATE_CHECK_QIANG_GANG_HU();
  }    
	else if (cmd == SERVER_PASS)
	{
		  handler_cmd_SERVER_PASS();
	}
	else if (cmd == SERVER_PENG)
	{
		handler_cmd_SERVER_PENG();
	}
	else if (cmd == SERVER_ANGGANG)
	{
		handler_cmd_SERVER_ANGGANG();
	}
	else if (cmd == SERVER_MINGGANG)
	{
		handler_cmd_SERVER_MINGGANG();
	}
  else if (cmd == SERVER_FANG_GANG)
  {
    handler_cmd_SERVER_FANG_GANG();
  }
  else if ( cmd == SERVER_ZIMOHU)
  {
    handler_cmd_SERVER_ZIMOHU();
  }
  else if (cmd == SERVER_FANG_PAO_HU)
  {
    handler_cmd_SERVER_FANG_PAO_HU();
  }
  else if (cmd == SERVER_QIANG_GANG_HU)
  {
    handler_cmd_SERVER_QIANG_GANG_HU();
  }
  else if (cmd == SERVER_GAME_READY_STAGE_BC)
  {
    handler_cmd_SERVER_GAME_READY_STAGE_BC();
  }
  else if (cmd == SERVER_GAME_END_BC)
  {
    handler_cmd_SERVER_GAME_END_BC();
  }
  else if (cmd == SERVER_REBIND_UC)
  {
    handler_cmd_SERVER_REBIND_UC();
  }
  else if (cmd == SERVER_ERROR_UC)
  {
    handler_cmd_SERVER_ERROR_UC();
  }
  else if (cmd == SERVER_DINGQUE_STARGE_BC)
  {
    handler_cmd_SERVER_DINGQUE_STARGE_BC();    
  }
  else if (cmd == SERVER_DINGQUE_SUCC_BC)
  {
    handler_cmd_SERVER_DINGQUE_SUCC_BC();
  }
  else if (cmd == SERVER_CHONG_FENG_JI_BC)
  {
    handler_cmd_SERVER_CHONG_FENG_JI_BC();
  }
  else if (cmd == SERVER_BAO_TING_SUCC_BC)
  {
    handler_cmd_SERVER_BAO_TING_SUCC_BC();
  }
	else if (cmd == SERVER_ZHE_REN_JI_BC)
  {
    handler_cmd_SERVER_ZHE_REN_JI_BC();
  }
  else if (cmd == SERVER_LOGIN_OTHER_DEVICE)
  {
    handler_cmd_SERVER_LOGIN_OTHER_DEVICE();    
  }
  else if (cmd == SERVER_GOLDROOM_LOGOUT_ROOM)
  {
    handler_cmd_SERVER_GOLDROOM_LOGOUT_ROOM();
  }
  else if (cmd == SERVER_BEGIN_ROBOT_OP_BC )
  {
    handler_cmd_SERVER_BEGIN_ROBOT_OP_BC();
  }
  else if (cmd == SERVER_CANCEL_ROBOT_OP_SUCC_BC)
  {
    handler_cmd_SERVER_CANCEL_ROBOT_OP_SUCC_BC();
  }
	return 0;
}

int LogicTask::handler_cmd_SERVER_ENTER_ROOM_UC()
{
	//_join_room_timer.stop();
	cout << uid << " is set down!" << endl;
	_on_seat = true;
	count_ = 0;
    return 0;
}

int LogicTask::handler_cmd_SERVER_ROOM_INFO_BC()
{
    return 0;
}
int LogicTask::handler_cmd_SERVER_GAME_START_BC()
{
	auto players = read_root["players"];
	for (auto& player : players)
	{
		if (player["uid"].asInt() == uid)
		{
			if (player.isMember("hole_mjs"))
			{
				auto hole_mjs = player["hole_mjs"];
				_hand_mjs.clear();
				for (auto& mj : hole_mjs)
				{
					_hand_mjs.push_back(Mj(mj.asInt()));
				}
			}
			break;
		}
	}
    return 0;
}
int LogicTask::handler_cmd_SERVER_READY_BC()
{
    return 0;
}
int LogicTask::handler_cmd_SERVER_GET_ONE_MJ()
{
    int rev_uid = read_root["uid"].asInt();
    if (rev_uid == this->uid)
    {
        last_mo_mj = read_root["mj"].asInt();
		_hand_mjs.push_back(Mj(last_mo_mj));
		rest_mjs = read_root["rest_mjs"].asInt();
        //printf("handler_cmd_SERVER_GET_ONE_MJ, uid:%d, last_mo_mj:%d.\n", uid, last_mo_mj);
	}
    return 0;
}

int LogicTask::handler_cmd_SERVER_OUT_ONE_MJ()
{
	int rev_uid = read_root["uid"].asInt();
	if (rev_uid == this->uid)
	{
		json_turn_hand_mjs(read_root);
	}
	return 0;
}
int LogicTask::handler_cmd_SERVER_OPERATE_CHECK_AFTER_GETIN_MJ()
{
    int rev_uid = read_root["uid"].asInt();
    if (rev_uid == uid)
    {
		int an_gang_flag = read_root["an_gang_flag"].asInt();
		int ming_gang_flag = read_root["ming_gang_flag"].asInt();
		int zi_mo_hu_flag = read_root["zi_mo_hu_flag"].asInt();
        if (zi_mo_hu_flag == 1)
        {
            zimo_hu_req();
        }
        else if (an_gang_flag == 1)
        {
            Json::Value arr1;
            arr1 = read_root["an_gang_mj_choose"];
			int mj = arr1[0].asInt();
            ang_gang_req(mj);
        }
		else if (ming_gang_flag == 1)
		{
			Json::Value arr1;
			arr1 = read_root["an_gang_mj_choose"];
			int mj = arr1[0].asInt();
			ming_gang_req();
		}
        else //出牌
        {
            out_mj_req();
        }
    }
  return 0;
}
int LogicTask::handler_cmd_SERVER_OPERATE_CHECK_OTHERS_PUTOUT_MJ()
{
  int rev_uid = read_root["uid"].asInt();
  if (rev_uid == uid)
  {
      int fang_pao_hu_flag = read_root["fang_pao_hu_flag"].asInt();
      int fang_gang_flag = read_root["fang_gang_flag"].asInt();
      int peng_flag = read_root["peng_flag"].asInt();
      if (fang_pao_hu_flag)
      {
		fang_pao_hu();     
      }
      else if (fang_gang_flag)
      {
          fang_gang_req();
      }
      else if (peng_flag)
      {
          peng_req();
      }
  }
  return 0;
}
int LogicTask::handler_cmd_SERVER_OPERATE_CHECK_AFTER_PENG()
{
	int rev_uid = read_root["uid"].asInt();
	if (rev_uid == uid)
	{
		int an_gang_flag = read_root["an_gang_flag"].asInt();
		if (an_gang_flag)
		{
			Json::Value arr1;
			arr1 = read_root["an_gang_mj_choose"];
			int mj = arr1[0].asInt();
			ang_gang_req(mj);
		}
		else
		{
			out_mj_req();
		}
	}
	return 0;
}
int LogicTask::handler_cmd_SERVER_OPERATE_CHECK_QIANG_GANG_HU()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_PASS()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_PENG()
{
  int rev_uid = read_root["uid"].asInt();
  if (rev_uid == this->uid)
  {
	  json_turn_hand_mjs(read_root);
  }
  return 0;
}
int LogicTask::handler_cmd_SERVER_ANGGANG()
{
	int rev_uid = read_root["uid"].asInt();
	if (rev_uid == this->uid)
	{
		json_turn_hand_mjs(read_root);
	}
	return 0;

  return 0;
}
int LogicTask::handler_cmd_SERVER_MINGGANG()
{
	int rev_uid = read_root["uid"].asInt();
	if (rev_uid == this->uid)
	{
		json_turn_hand_mjs(read_root);
	}

  return 0;
}
int LogicTask::handler_cmd_SERVER_FANG_GANG()
{
	int rev_uid = read_root["uid"].asInt();
	if (rev_uid == this->uid)
	{
		json_turn_hand_mjs(read_root);
	}

  return 0;
}
int LogicTask::handler_cmd_SERVER_ZIMOHU()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_FANG_PAO_HU()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_QIANG_GANG_HU()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_GAME_READY_STAGE_BC()
{
	//goldroom_logout_req();
	//join_room_req();
	RunOnce(3, [this](const boost::system::error_code& err) {ready_req(); });
	return 0;
}
int LogicTask::handler_cmd_SERVER_GAME_END_BC()
{
	if (read_root.isMember("quick_match_info"))
	{
		RunOnce(15, [this](const boost::system::error_code& err) {goldroom_logout_req(); });
	}
	board_cnt++;
	return 0;
}
int LogicTask::handler_cmd_SERVER_REBIND_UC()
{
	//_join_room_timer.stop();
	cout << uid << " is set down!" << endl;

	_on_seat = true;
  return 0;
}
int LogicTask::handler_cmd_SERVER_ERROR_UC()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_DINGQUE_STARGE_BC()
{
	int dq = calculate_min_que(_hand_mjs);
	do_ding_que(dq);
	return 0;
}
int LogicTask::handler_cmd_SERVER_DINGQUE_SUCC_BC()
{
	auto players = read_root["players"];
	for (auto& player : players)
	{
		if (player["uid"].asInt() == uid)
		{
			_has_que = player["dq_val"].asInt();
			break;
		}
	}
  return 0;
}
int LogicTask::handler_cmd_SERVER_CHONG_FENG_JI_BC()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_BAO_TING_SUCC_BC()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_ZHE_REN_JI_BC()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_LOGIN_OTHER_DEVICE()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_GOLDROOM_LOGOUT_ROOM()
{
  return 0;
}
int LogicTask::handler_cmd_SERVER_BEGIN_ROBOT_OP_BC()
{
	int rev_uid = read_root["uid"].asInt();
	if (rev_uid == this->uid)
	{
		cout << uid << "to be a robot" << endl;
		cancel_robot();
	}
	return 0;
}
int LogicTask::handler_cmd_SERVER_CANCEL_ROBOT_OP_SUCC_BC()
{
  return 0;
}

Mj LogicTask::choose_outmj()
{
	if (_has_que != 0)
	{
		for (auto& mj : _hand_mjs)
		{
			if (mj.val/10 == _has_que)
			{
				return mj;
			}
		}
	}
	std::sort(_hand_mjs.begin(), _hand_mjs.end(), [](const Mj& a, const Mj& b) {return (a < b); });
	int mjs[14] = { 0 };
	int i(0);
	for (auto& mj : _hand_mjs)
	{
		mjs[i++] = mj.val;
	}
// 	cout << "hands: " << printHands(_hand_mjs) << endl;;
	int select[14] = { 0 };
	vector<Mj> mix_mjs;
	//检查有没有三不沾的牌
	auto check_alone = [](vector<Mj> mjs)->Mj {
		if (mjs.empty())
		{
			return Mj();
		}
		pair<Mj, int> mj_between = make_pair(Mj(), 1);//单麻将和距离最近的牌的距离
		for (int n(0); n < mjs.size(); n++)
		{
			int abs_mj(100);
			if (n != 0)
			{
				if (mjs[n] == mjs[n - 1])continue;
				else
				{
					abs_mj = abs(mjs[n].val - mjs[n - 1].val);
				}
			}
			if (n != mjs.size() - 1)
			{
				if (mjs[n] == mjs[n + 1])continue;
				else
				{
					int t_abs_mj = abs(mjs[n].val - mjs[n + 1].val);
					abs_mj = (t_abs_mj < abs_mj) ? t_abs_mj : abs_mj;
				}
			}
			if (abs_mj > mj_between.second)
			{
				mj_between = make_pair(Mj(mjs[n]), abs_mj);
			}
		}
		return Mj(mj_between.first);
	};
	std::function<bool(int*,int*,int)> judge_hu = [&](int* pi_mj, int* pi_select, int num) {
		int i_max, i_min, i_mid;
		int i_mark1, i_mark2;
		int i_have3 = 0;
		for (int i = 0; i<num; i++)
		{
			if (pi_select[i])
				continue;
			else
			{
				i_mark1 = i;
			}

			for (int j = i + 1; j<num; j++)
			{
				if (i == j)
					continue;
				if (pi_select[j])
					continue;
				else
				{
					i_mark2 = j;
				}

				for (int k = j + 1; k<num; k++)
				{
					if (i == k || j == k)
						continue;
					if (pi_select[k])
						continue;

					/*说明可以找到3张未选择过的牌,
					*如果最后i_have3 == 0,
					*说明此时只有2张牌了.下面可以用i_mark1,i_mark2获得此二张. */
					i_have3 = 1;

					i_max = 0;
					i_min = 100;

					i_max = std::max(pi_mj[i], std::max(pi_mj[j], pi_mj[k]));
					i_min = std::min(pi_mj[i], std::min(pi_mj[j], pi_mj[k]));
					i_mid = (i_max + i_min) / 2;

					if (pi_mj[i] == pi_mj[j]
						&& pi_mj[i] == pi_mj[k])  //表示能组成刻子
					{
						//do nothing
					}
					else if (i_max - i_min == 2
						&& (pi_mj[i] == i_mid || pi_mj[j] == i_mid || pi_mj[k] == i_mid)) //表示能组成顺子
					{
						//do nothing
					}
					else
						continue;

					//记录下来 下面递归
					pi_select[i] = pi_select[j] = pi_select[k] = 1;

					if (!judge_hu(pi_mj, pi_select, num))
					{
						pi_select[i] = pi_select[j] = pi_select[k] = 0; //递归一次结束,返回
						continue;
					}

					//选择的3张成刻、顺，而剩下的和了
					return true;
				}

				//只剩两张牌, 相等
				if ((i_have3 == 0) && pi_mj[i_mark1] == pi_mj[i_mark2])
				{
					return true;
				}
			}
		}
		//递归玩，不满足胡牌
		vector<Mj> mix;
		for (int n(0); n < num; n++)
		{
			if (pi_select[n] == 0)
			{
				mix.push_back(Mj(pi_mj[n]));
			}
		}
		if (mix_mjs.empty() ||  mix.size()<mix_mjs.size())
		{
			mix_mjs = mix;
		}

		return false;
	};
	auto mj = check_alone(_hand_mjs);
// 	cout << "all alone is :" << mj.val << endl;
	if (mj != 0)
	{
		return mj;
	}
	judge_hu(mjs, select, _hand_mjs.size());
// 	cout << "mixs : " << printHands(mix_mjs) << endl;
	std::sort(mix_mjs.begin(), mix_mjs.end(), [](const Mj& a, const Mj& b) {return (a < b); });
	auto choose_mix = [&](vector<Mj> mjs) -> Mj {
		//组牌之后再次检查有没有三不沾的牌
		auto mj = check_alone(mjs);
		if (mj != 0)
		{
			return mj;
		}
		//剔除对子打单牌
		vector<Mj> t_mjs;
		int p_mjs[14] = { 0 };
		int i(0);
		for (auto& mj : mjs)
		{
			p_mjs[i++] = mj.val;
		}
		int p_select[14] = { 0 };
		for (int n(1); n < i; n++)
		{
			if (p_mjs[n - 1] == p_mjs[n])
			{
				p_select[n - 2] = 1;
				p_select[n] = 1;
			}
		}
		for (int n(0); n < i; n++)
		{
			if (p_select[n] == 0)
			{
				t_mjs.push_back(Mj(p_mjs[n]));
			}
		}
		//如果是空，说明全是对子
		if (t_mjs.empty())
		{
			int color[3];
			tie(color[0],color[1],color[2]) = Mj::GetColorNum(_hand_mjs);
			pair<Mj, int> color_pair = make_pair(Mj(),100);
			for (auto& mj : t_mjs)
			{
				int cl = mj.color()-1;
				if (cl != -1 && color_pair.second > color[cl])
				{
					color_pair.second = color[cl];
					color_pair.first = mj;
				}
			}
			return color_pair.first;
		}
		else //	如果非空，说明只有2连
		{
			pair<Mj, int> distance_pair = make_pair(Mj(), 0);
			for (auto& mj : t_mjs)
			{
				int dis = abs((mj.val % 10) - 5);
				if (dis > distance_pair.second)
				{
					distance_pair.second = dis;
					distance_pair.first = mj;
				}
			}
			return distance_pair.first;
		}
	};
	mj = choose_mix(mix_mjs);
// 	cout << "mix alone is :" << mj.val << endl;
	if (mj != 0)
	{
		return mj;
	}
	return Mj(last_mo_mj);
}


